package devices

import (
	"context"

	"gitee.com/zhuhuan12/go-modbus"
	"github.com/gogf/gf/v2/frame/g"
)

// 物宇宙的粒子数
type WyzParticle struct {
	Product    string  // 产品Key
	ModbusAddr int8    // modbus地址
	RunMin     int     // 运行时间 每隔多少分钟运行一分钟
	RunMode    int     // 0=》正常运行，1=》停止运行，2=》超控模式
	Um03Yz     int     // um03 粒子数，两位小数
	Um05Yz     int     // um05 粒子数，两位小数
	Um10Yz     int     // um1 粒子数，两位小数
	Um30Yz     int     // um2.5 粒子数，两位小数
	Um50Yz     int     // um5 粒子数，两位小数
	Um100Yz    int     // um10 粒子数，两位小数
	TempYz     int     // 温度，两位小数
	HumYz      int     // 湿度，两位小数
	BardRate   int     // 波特率 1=>9600,2=>4800,3=>115200
	NetId      int     // 网络ID 0000-00FF
	NetAddr    int     // 网络地址 0000-FFFF
	Unit       int     // 单位 0=>pcl/L,1=>pcs/m3,2=>pcs/ft3
	Um03       int     // um03 粒子数
	Um05       int     // um05 粒子数
	Um10       int     // um1 粒子数
	Um30       int     // um2.5 粒子数
	Um50       int     // um5 粒子数
	Um100      int     // um10 粒子数
	Temp       float64 // 温度
	Hum        float64 // 湿度
}

func (w *WyzParticle) NewDevice(modbusValue int8) Device {
	return &WyzParticle{
		ModbusAddr: modbusValue,
		Product:    "lizishu",
		RunMin:     5,
		Um03Yz:     1,
		Um05Yz:     1,
		Um10Yz:     1,
		Um30Yz:     1,
		Um50Yz:     1,
		Um100Yz:    1,
		TempYz:     1,
		HumYz:      1,
		BardRate:   1,
		NetId:      12,
		NetAddr:    1000,
		Unit:       0,
	}
}

func (w *WyzParticle) GetProductKey() string {
	return w.Product
}

func (w *WyzParticle) GetModbusAddr() int8 {
	return w.ModbusAddr
}

func (w *WyzParticle) HandleData(data []byte) ([]byte, error) {
	out := []byte{}
	if data[1] == 0x03 {
		beginAddr := int(data[2])<<8 | int(data[3])
		readLen := int(data[4])<<8 | int(data[5])

		out = []byte{byte(w.ModbusAddr), 0x03, byte(readLen * 2)}
		for i := 0; i < readLen; i++ {
			addr := beginAddr + i // 对应的地址
			switch addr {
			case 0:
				g.Log().Debug(context.Background(), "modbus_addr", w.ModbusAddr)
				out = append(out, 0, byte(w.ModbusAddr))
			case 1:
				g.Log().Debug(context.Background(), "runmin", w.RunMin)
				out = append(out, byte(w.RunMin>>8), byte(w.RunMin))
			case 2:
				g.Log().Debug(context.Background(), "runmode", w.RunMode)
				out = append(out, byte(w.RunMode>>8), byte(w.RunMode))
			case 3:
				g.Log().Debug(context.Background(), "um03yz", w.Um03Yz)
				out = append(out, byte(w.Um03Yz>>8), byte(w.Um03Yz))
			case 4:
				g.Log().Debug(context.Background(), "um05yz", w.Um05Yz)
				out = append(out, byte(w.Um05Yz>>8), byte(w.Um05Yz))
			case 5:
				g.Log().Debug(context.Background(), "um10yz", w.Um10Yz)
				out = append(out, byte(w.Um10Yz>>8), byte(w.Um10Yz))
			case 6:
				g.Log().Debug(context.Background(), "um30yz", w.Um30Yz)
				out = append(out, byte(w.Um30Yz>>8), byte(w.Um30Yz))
			case 7:
				g.Log().Debug(context.Background(), "um50yz", w.Um50Yz)
				out = append(out, byte(w.Um50Yz>>8), byte(w.Um50Yz))
			case 8:
				g.Log().Debug(context.Background(), "um100yz", w.Um100Yz)
				out = append(out, byte(w.Um100Yz>>8), byte(w.Um100Yz))
			case 9:
				g.Log().Debug(context.Background(), "tempyz", w.TempYz)
				out = append(out, byte(w.TempYz>>8), byte(w.TempYz))
			case 10:
				g.Log().Debug(context.Background(), "humyz", w.HumYz)
				out = append(out, byte(w.HumYz>>8), byte(w.HumYz))
			case 11:
				g.Log().Debug(context.Background(), "bardrate", w.BardRate)
				out = append(out, byte(w.BardRate>>8), byte(w.BardRate))
			case 12:
				g.Log().Debug(context.Background(), "netid", w.NetId)
				out = append(out, byte(w.NetId>>8), byte(w.NetId))
			case 13:
				g.Log().Debug(context.Background(), "netaddr", w.NetAddr)
				out = append(out, byte(w.NetAddr>>8), byte(w.NetAddr))
			case 14:
				g.Log().Debug(context.Background(), "unit", w.Unit)
				out = append(out, byte(w.Unit>>8), byte(w.Unit))
			default:
				out = append(out, 0, 0)
			}
		}
	} else if data[1] == 0x06 {
		addr := int(data[2])<<8 | int(data[3])
		if addr == 0x00 {
			g.Log().Debug(context.Background(), "set modbus_addr", w.ModbusAddr)
			w.ModbusAddr = int8(int(data[4])<<8 | int(data[5]))
		}
		if addr == 0x01 {
			g.Log().Debug(context.Background(), "set runmin", w.RunMin)
			w.RunMin = int(int(data[4])<<8 | int(data[5]))
		}
		if addr == 0x02 {
			g.Log().Debug(context.Background(), "set runmode", w.RunMode)
			w.RunMode = int(int(data[4])<<8 | int(data[5]))
		}
		if addr == 0x03 {
			g.Log().Debug(context.Background(), "set um03yz", w.Um03Yz)
			w.Um03Yz = int(int(data[4])<<8 | int(data[5]))
		}
		if addr == 0x04 {
			g.Log().Debug(context.Background(), "set um05yz", w.Um05Yz)
			w.Um05Yz = int(int(data[4])<<8 | int(data[5]))
		}
		if addr == 0x05 {
			g.Log().Debug(context.Background(), "set um10yz", w.Um10Yz)
			w.Um10Yz = int(int(data[4])<<8 | int(data[5]))
		}
		if addr == 0x06 {
			g.Log().Debug(context.Background(), "set um30yz", w.Um30Yz)
			w.Um30Yz = int(int(data[4])<<8 | int(data[5]))
		}
		if addr == 0x07 {
			g.Log().Debug(context.Background(), "set um50yz", w.Um50Yz)
			w.Um50Yz = int(int(data[4])<<8 | int(data[5]))
		}
		if addr == 0x08 {
			g.Log().Debug(context.Background(), "set um100yz", w.Um100Yz)
			w.Um100Yz = int(int(data[4])<<8 | int(data[5]))
		}
		if addr == 0x09 {
			g.Log().Debug(context.Background(), "set tempyz", w.TempYz)
			w.TempYz = int(int(data[4])<<8 | int(data[5]))
		}
		if addr == 0x0A {
			g.Log().Debug(context.Background(), "set humyz", w.HumYz)
			w.HumYz = int(int(data[4])<<8 | int(data[5]))
		}
		if addr == 0x0B {
			g.Log().Debug(context.Background(), "set bardrate", w.BardRate)
			w.BardRate = int(int(data[4])<<8 | int(data[5]))
		}
		if addr == 0x0C {
			g.Log().Debug(context.Background(), "set netid", w.NetId)
			w.NetId = int(int(data[4])<<8 | int(data[5]))
		}
		if addr == 0x0D {
			g.Log().Debug(context.Background(), "set netaddr", w.NetAddr)
			w.NetAddr = int(int(data[4])<<8 | int(data[5]))
		}
		if addr == 0x0E {
			g.Log().Debug(context.Background(), "set unit", w.Unit)
			w.Unit = int(int(data[4])<<8 | int(data[5]))
		}
		out = []byte{byte(w.ModbusAddr), 0x06, byte(addr >> 8), byte(addr), data[4], data[5]}
	} else if data[1] == 0x04 {
		w.Um03 = w.Um03 + 1
		w.Um05 = w.Um05 + 2
		w.Um10 = w.Um10 + 3
		w.Um30 = w.Um30 + 4
		w.Um50 = w.Um50 + 5
		w.Um100 = w.Um100 + 6
		w.Temp += 0.1
		w.Hum += 0.2
		g.Log().Debug(context.Background(), "粒子数", w)
		beginAddr := int(data[2])<<8 | int(data[3])
		readLen := int(data[4])<<8 | int(data[5])
		out = []byte{byte(w.ModbusAddr), 0x04, byte(readLen * 2)}
		for i := 0; i < readLen; i++ {
			addr := beginAddr + i // 对应的地址
			switch addr {
			case 0:
				um3hh := w.Um03 >> 24 & 0xFF
				um3hl := w.Um03 >> 16 & 0xFF
				out = append(out, byte(um3hh), byte(um3hl))
			case 1:
				um3lh := w.Um03 >> 8 & 0xFF
				um3ll := w.Um03 & 0xFF
				out = append(out, byte(um3lh), byte(um3ll))
			case 2:
				um5hh := w.Um05 >> 24 & 0xFF
				um5hl := w.Um05 >> 16 & 0xFF
				out = append(out, byte(um5hh), byte(um5hl))
			case 3:
				um5lh := w.Um05 >> 8 & 0xFF
				um5ll := w.Um05 & 0xFF
				out = append(out, byte(um5lh), byte(um5ll))
			case 4:
				um10hh := w.Um10 >> 24 & 0xFF
				um10hl := w.Um10 >> 16 & 0xFF
				out = append(out, byte(um10hh), byte(um10hl))
			case 5:
				um10lh := w.Um10 >> 8 & 0xFF
				um10ll := w.Um10 & 0xFF
				out = append(out, byte(um10lh), byte(um10ll))
			case 6:
				um30hh := w.Um30 >> 24 & 0xFF
				um30hl := w.Um30 >> 16 & 0xFF
				out = append(out, byte(um30hh), byte(um30hl))
			case 7:
				um30lh := w.Um30 >> 8 & 0xFF
				um30ll := w.Um30 & 0xFF
				out = append(out, byte(um30lh), byte(um30ll))
			case 8:
				um50hh := w.Um50 >> 24 & 0xFF
				um50hl := w.Um50 >> 16 & 0xFF
				out = append(out, byte(um50hh), byte(um50hl))
			case 9:
				um50lh := w.Um50 >> 8 & 0xFF
				um50ll := w.Um50 & 0xFF
				out = append(out, byte(um50lh), byte(um50ll))
			case 10:
				um100hh := w.Um100 >> 24 & 0xFF
				um100hl := w.Um100 >> 16 & 0xFF
				out = append(out, byte(um100hh), byte(um100hl))
			case 11:
				um100lh := w.Um100 >> 8 & 0xFF
				um100ll := w.Um100 & 0xFF
				out = append(out, byte(um100lh), byte(um100ll))
			case 12:
				temph := int(w.Temp*100) >> 8 & 0xFF
				templ := int(w.Temp*100) & 0xFF
				out = append(out, byte(temph), byte(templ))
			case 13:
				humh := int(w.Hum*100) >> 8 & 0xFF
				huml := int(w.Hum*100) & 0xFF
				out = append(out, byte(humh), byte(huml))
			default:
				out = append(out, 0, 0)
			}
		}
	}
	intValue := modbus.CRC16(out)
	out = append(out, byte(intValue), byte(intValue>>8))
	return out, nil
}
